﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace Common
{
    public abstract class DataPaser
    {
        public string FileName { get; set; }
        public DataPaser(string fileName)
        {
            FileName = fileName;
            if (!File.Exists(FileName))
                throw new Exception(string.Format("文件： {0} 不存在", FileName));
        }
        public string ReadLastNLines(int nLine)
        {
            return ReadLastLine(FileName, nLine, Encoding.Default);
        }
        #region 静态方法:从后面开始读数据行
        /// <summary>
        /// 读取文本文件最后的内容
        /// </summary>
        /// <param name="AFileName">文件名</param>
        /// <param name="ALineCount">行数</param>
        /// <param name="AEncoding">字符编码</param>
        /// <returns>返回读取的内容</returns>
        public static string ReadLastLine(string AFileName, int ALineCount, Encoding AEncoding)
        {
            if (ALineCount <= 0) return string.Empty;
            if (!File.Exists(AFileName)) return string.Empty; // 文件不存在
            if (AEncoding == null) AEncoding = Encoding.Default;
            using (FileStream vFileStream = new FileStream(AFileName,
                FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {

                if (vFileStream.Length <= 0) return string.Empty; // 空文件
                byte[] vBuffer = new byte[0x1000]; // 缓冲区
                int vReadLength; // 读取到的大小
                int vLineCount = 0; // 读取的行数
                int vReadCount = 0; // 读取的次数
                int vScanCount = 0; // 扫描过的字符数
                long vOffset = 0; // 向后读取的位置
                do
                {
                    vOffset = vBuffer.Length * ++vReadCount;
                    int vSpace = 0; // 偏移超出的空间
                    if (vOffset >= vFileStream.Length) // 超出范围
                    {
                        vSpace = (int)(vOffset - vFileStream.Length);
                        vOffset = vFileStream.Length;
                    }
                    vFileStream.Seek(-vOffset, SeekOrigin.End); //“SeekOrigin.End”反方向偏移读取位置

                    vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length - vSpace);
                    #region 所读的缓冲里有多少行
                    for (int i = vReadLength - 1; i >= 0; i--)
                    {
                        if (vBuffer[i] == 10)
                        {
                            if (vScanCount > 0) vLineCount++; // #13#10为回车换行
                            if (vLineCount >= ALineCount) break;
                        }
                        vScanCount++;
                    }
                    #endregion 所读的缓冲里有多少行
                } while (vReadLength >= vBuffer.Length && vOffset < vFileStream.Length &&
                    vLineCount < ALineCount);

                if (vReadCount > 1) // 读的次数超过一次，则需重分配缓冲区
                {
                    vBuffer = new byte[vScanCount];
                    vFileStream.Seek(-vScanCount, SeekOrigin.End);
                    vReadLength = vFileStream.Read(vBuffer, 0, vBuffer.Length);
                }
                return AEncoding.GetString(vBuffer, vReadLength - vScanCount, vScanCount);
            }
        }

        #endregion
    }

}
